/**
 * 
 */
package systole.processor;

import java.math.BigDecimal;
import systole.domain.signals.Segment;
import systole.domain.signals.Signal;

/**
 *
 * This class slice the filtered signal in many segments.
 *
 *
 * @author juan
 * 
 */
public class Slicer {


    private final int initOfSegment = 60;
    private final int deviationOfMax = 120;
    private final int minToMaxDistance = 40;
    private final int maxLengthOfSegment = 176;
    private final int offset = 5;
    private final BigDecimal fifty = new BigDecimal(50);

    /**
     *
     * @param rawSignal The raw signal to segment.
     * @param initPos  The position where the processor will start to search
     * @return the position where the segment start
     */
    private int obtainTheStartOfSegment(Segment rawSignal,
            Integer initPos) {
        // Los primeros 60 puntos se descartan porque ¿siempre? estan con basura

        int endOfSegment = initPos + this.deviationOfMax;

        int posOfMax = initPos + rawSignal.subSegment(initPos, endOfSegment).getPosOfMax();
        int initOfCurrentSegment = posOfMax - this.minToMaxDistance;
        if (initOfCurrentSegment < 0) {
            initOfCurrentSegment = 0;
        }
        return initOfCurrentSegment;
    }

    private int obtainTheEndOfSegment(Segment rawSignal, Integer endPos) {

        int initSegment = endPos - 40;
        int posOfMin = initSegment + rawSignal.subSegment(initSegment, endPos).getPosOfMin();

        return posOfMin;
    }

    private Segment obtainNextSegment(Segment rawSignal, Integer initPos) {
        int initOfActalSegment = this.obtainTheStartOfSegment(rawSignal,
                initPos);
        int endOfActualSegment = this.obtainTheEndOfSegment(rawSignal, initOfActalSegment + this.maxLengthOfSegment);//initOfActalSegment+this.maxLengthOfSegment;
        Segment segment = rawSignal.subSegment(initOfActalSegment,
                endOfActualSegment);        
        segment = segment.normalize();
        int posOfMax = segment.getPosOfMax();
        int fiftyPos = segment.looksPositionOfNearestValueOnSubSegment(fifty, 0, posOfMax);
        int dif = fiftyPos - 10;
        if (dif > 0) {
            segment = segment.subSegment(dif, endOfActualSegment);
        } else if (dif < 0) {
            BigDecimal firstValue = segment.get(0);
            while (dif != 0) {
                segment.add(0, firstValue);
                dif++;
            }
        }
        segment = segment.normalize();
        return segment;
    }

    /**
     *
     * @param rawSignal The Segment inverted and normalized.
     * @return Signal
     */
    public Signal sliceSignal(Segment rawSignal) {
        Signal processed = new Signal();
        int relativeInitOfSegment = this.initOfSegment;
        Segment segment;
        int i = 0;
        while (relativeInitOfSegment < rawSignal.size()) {
            segment = this.obtainNextSegment(rawSignal, relativeInitOfSegment);
            processed.getSegments().add(segment);
            relativeInitOfSegment = relativeInitOfSegment + segment.size() + this.offset;
            i++;
        }
        return processed;
    }
}
